package com.xzm.cglib;

import com.xzm.proxy.IProducer;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @author 3052
 * @create 2020-07-29 15:32
 */
public class Client {
    public static void main(String[] args) {
        final Producer producer = new Producer();
        /**
         * 动态代理
         * 特点：字节码随用随创建，随用随加载
         * 作用：不修改源码的基础上对方法增强
         * 分类：
         *      基于子类的动态代理
         * 基于子类的动态代理：
         *      涉及的类：Enhancer
         *      提供者;第三方
         *      如何创建代理对象：
         *          使用Enhancer类中的Create方法
         *      创建代理对象的要求：
         *          被代理的类不能是最终类
         *       Create方法的参数：
         *              class：字节码，用于指定被代理对象的字节码
         *              callback:用于提供增强的代码
         *                  他是让我们写如何代理，我们一般都是写一些该接口的实现类，通常情况下都是匿名内部类。
         *                  此接口的实现类都是谁用谁写
         *                  我们写的一般都是该接口的子接口实现类：MethodInterceptor
         *
         */
        Producer cglibProducer = (Producer) Enhancer.create(producer.getClass(), new MethodInterceptor() {
            /**
             * 执行被代理类的任何方法都会经过该方法
             * @param o
             * @param method
             * @param objects
             * 以上三个参数的含义和基于接口的动态代理invoke方法是一样的
             * @param methodProxy  当前执行方法的代理对象
             * @return
             * @throws Throwable
             */
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                //提供增强的代码
                Object returnValue = null;
                //1.获得方法执行的参数
                Float money = (Float) objects[0];
                if("saleProduct".equals(method.getName())){
                    returnValue=method.invoke(producer,money*0.8f);
                }
                return returnValue;
            }
        });
        cglibProducer.saleProduct(1200f);

    }
}
